package gui;


import javax.swing.JPanel;
import javax.swing.JScrollPane;

import javax.swing.border.LineBorder;

import observer.Broker;
import observer.Observer;

import utility.Auto;
import utility.Cell;
import utility.Triple;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.util.Iterator;

import java.util.Set;
import javax.swing.ScrollPaneConstants;

public class MapPanel extends JPanel implements Observer{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final int SIZESQAURE = 32;

	private Image strada,incrocio,spazio,autoTmp,streetX,pointAuto;

	private Broker broker;

	private MouseListnerMap mouseListener;
	
	
	public MapPanel(Broker broker) {
				
		this.broker = broker;
		this.mouseListener = new MouseListnerMap(broker);
		this.addMouseListener(mouseListener);

		//matrix = broker.getParser().getMatrix();
		
		this.setPreferredSize(new Dimension(1000, 1000));
		
		
		broker.addObserver(this);

		//carico le immagini
		strada = getImage("img\\grey.gif");
		incrocio = getImage("img\\greyD.gif");
		spazio = getImage("img\\green.gif");
		autoTmp = getImage("img\\car.gif");
		streetX = getImage("img\\streetX.png");
		pointAuto = getImage("img\\red.jpg");

		setBorder(new LineBorder(new Color(0, 0, 0), 2, true));

	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);

		if(broker.getParser() != null)
		{	
			for (int i = 0; i < broker.getParser().getSizeX(); i++) {
				for (int j = 0; j < broker.getParser().getSizeY(); j++) {

					String nameStreetTmp= broker.getParser().getCellMatrix(i, j).getStreetName();

					//disegno la matrice che rappresenta la mappa stradale!
					switch (broker.getParser().getCellMatrix(i, j).getType()) {

					case STREET:

						//controllo sulla direzione della strada!!!
						if(broker.getParser().getCellMatrix(i+1, j).getStreetName().equals(nameStreetTmp) || broker.getParser().getCellMatrix(i-1, j).getStreetName().equals(nameStreetTmp))
						{
							g.drawImage(streetX, j*SIZESQAURE, i*SIZESQAURE, null);
						}
						else if(broker.getParser().getCellMatrix(i, j+1).getStreetName().equals(nameStreetTmp) || broker.getParser().getCellMatrix(i, j-1).getStreetName().equals(nameStreetTmp))
						{
							g.drawImage(streetX, j*SIZESQAURE, i*SIZESQAURE, null);
						}

						break;

					case INTERSECTION:
						g.drawImage(incrocio, j*SIZESQAURE, i*SIZESQAURE, null);
						break;

					case VACUUM:
						g.drawImage(spazio, j*SIZESQAURE, i*SIZESQAURE, null);
						break;

					default:
						break;
					}
				}
			}

			//disegno la base della matrice in nero!!!(TEMPORANEAMENTE!!!)
			g.setColor(Color.BLACK);
			for (int i = 0; i < broker.getParser().getSizeX(); i++) {	
				g.drawLine(0, i*SIZESQAURE, broker.getParser().getSizeY()*SIZESQAURE, i*SIZESQAURE);
			}
			for (int i = 0; i < broker.getParser().getSizeY(); i++) {
				g.drawLine(i*SIZESQAURE,0, i*SIZESQAURE, broker.getParser().getSizeX()*SIZESQAURE);
			}
		}

		//verifico la presenza di auto nella mappa
		if( broker.getNavigatore() != null &&
				!broker.getNavigatore().getAutos().isEmpty()){

			//disegno le macchine presenti nella mappa!
			Set<Integer> setAuto = broker.getNavigatore().getAutos().keySet();
			Iterator<Integer> iter = setAuto.iterator();

			while(iter.hasNext())
			{
				Auto a = broker.getNavigatore().getAuto(iter.next());

				int x = (int)a.getAutoPosition().getWidth();
				int y = (int)a.getAutoPosition().getHeight();

				Triple<Integer, Integer, String> sourceAuto=broker.getParser().getGraph().getEdgeSource(a.getWay().get(0));

				Triple<Integer, Integer, String>  targetAuto=broker.getParser().getGraph().getEdgeTarget(a.getWay().get(0));

				//si occupa della gestione grafica dell'incorcio!
//				if(matrix[x][y].getType().equals(Cell.typeCell.INTERSECTION) || 
//						matrix[x][y].getType().equals(Cell.typeCell.POINTCUT))
//				{
//				}
//             //logica dentro alla strada che mantiene l'auto a destra!
//				else{

					if(sourceAuto.getFirst() == targetAuto.getFirst())
					{
						if(sourceAuto.getSecond() > targetAuto.getSecond())
							g.drawImage(pointAuto, y*SIZESQAURE, x*SIZESQAURE, null);
						else
							if(sourceAuto.getSecond() < targetAuto.getSecond())
								g.drawImage(pointAuto, y*SIZESQAURE+(SIZESQAURE/2), x*SIZESQAURE+(SIZESQAURE/2), null);

					}
					else if(sourceAuto.getSecond() == targetAuto.getSecond())
					{

						if(sourceAuto.getFirst() > targetAuto.getFirst())
							g.drawImage(pointAuto, y*SIZESQAURE+(SIZESQAURE/2), x*SIZESQAURE, null);
						else
							if(sourceAuto.getFirst() < targetAuto.getFirst())
								g.drawImage(pointAuto, y*SIZESQAURE, x*SIZESQAURE+(SIZESQAURE/2), null);
					}

				}

			
		}

		//rimpiazzare con un thread che si occupa del repaint della mappa!
		this.repaint(100);

	}


	//funzione di utilita per il caricamento delle immagini
	//come input vuole il path dell' immagine da caricare!!!
	public Image getImage(String pathImage) {

		MediaTracker mt = new MediaTracker(this);

		Image img = Toolkit.getDefaultToolkit().getImage(pathImage);

		int id = 0;
		mt.addImage(img, id);
		try {
			mt.waitForID(id);

		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}

		return img;

	}

	public void setCursorSelectionAuto(){

		setCursor(new Cursor(Cursor.HAND_CURSOR));
	}

	public void restoreDeafaultCursor(){

		setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
	}


	@Override
	public void update(Object object) {
		// TODO Auto-generated method stub

		if(object.equals("loadMap"))
			this.repaint();
		else if(object.equals("activeAddAuto")){

			setCursorSelectionAuto();

		}
		else if(object.equals("disactiveAddAuto")){

			restoreDeafaultCursor();
		}
		
		else if(object.equals("repaintMapPanel"))
		{
			this.repaint();
		}

		
		
		
	}

}
